package com.atguigu.lease.common.utils;

import com.atguigu.lease.common.exception.LeaseException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import java.util.Date;

/**
 * @author Ahmad
 * @date 2024/12/25 0:01
 * @description Jwt工具类
 * 用于生成Token  和解析Token
 */
public class JwtUtil {
    private static long tokenExpiration = 60 * 60 * 1000L;//token有效期1小时

    /**
     * 密钥
     * <p>
     * M0PKKI6pYGVWWfDZw90a0lTpGYX1d4AQ   这个就是用对应的加密算法加密过的密钥
     */
    private static SecretKey tokenSignKey = Keys.hmacShaKeyFor("c0cc0dfdfaef2370e4d56711175fe349def6ed4cba25d3c7a01fc6ef6568220d".getBytes());

    /**
     * 生成token：携带登录用户的信息
     * 登录用户的信息：1.用户名（账号）username，  2.用户id 作为Token的 负载payload
     *
     * @param userId
     * @param username
     * @return
     */
    public static String createToken(Long userId, String username) {
        String token = Jwts.builder()
                .setSubject("sysUser-token")//设置主题为sysUser-token
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))//设置过期时间,就是当前时间+有效期
                .claim("userId", userId)//claim  声明，在JWT的第二部分负载进行声明，设置登录用户的信息（负载）
                .claim("username", username)
                .signWith(tokenSignKey)//设置签名，有效期时间
                .compressWith(CompressionCodecs.GZIP)//设置压缩方式
                .compact();//将上面的信息组合在一起，生成最终的Token字符串
        return token;
    }

    /**
     * 解析token
     *
     * @param token
     * @return
     */
    public static Claims parseToken(String token) {
        try {
            Jws<Claims> claimsJws = Jwts.parserBuilder()
                    .setSigningKey(tokenSignKey)//设置签名密钥
                    .build()
                    .parseClaimsJws(token);//以上就是解析token字符串，获取里面的信息的过程

            Claims body = claimsJws.getBody();
            //获取负载信息，也就是登录用户的信息
            return body;

        } catch (ExpiredJwtException e) {
            throw new LeaseException(ResultCodeEnum.TOKEN_EXPIRED);//token过期
        } catch (JwtException e) {
            throw new LeaseException(ResultCodeEnum.TOKEN_INVALID);//token非法
        }
    }
}